home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / TSFAQP15.ZIP / FAQPAS.TXT next >
Internet Message Format  |  1993-08-18  |  64KB

  1. From ts@uwasa.fi Wed Aug 18 00:00:00 1993
  2. Subject: FAQPAS.TXT contents                   (All rights reserved)
  3.  
  4. FAQPAS.TXT Frequently (and not so frequently) asked Turbo Pascal
  5. questions with Timo's answers. The questions are in no particular
  6. order.
  7. Comments and corrections are solicited.
  8.  
  9. ..................................................................
  10. Prof. Timo Salmi      Co-moderator of comp.archives.msdos.announce
  11. Moderating  at  garbo.uwasa.fi anonymous FTP archives 128.214.87.1
  12. Faculty of Accounting & Industrial Management; University of Vaasa
  13. Internet:  ts@uwasa.fi  Bitnet:  salmi@finfun; FI-65101,   Finland
  14.  
  15. -------------------------------------------------------------------
  16.  1) How do I disable or capture the break key in Turbo Pascal?
  17.  2) How do I get a printed documentation of my students' TP runs?
  18.  3) What is the code for the weekday of a given date?
  19.  4) Need a program to format Turbo Pascal source code consistently
  20.  5) Can someone give me advice for writing a tsr program?
  21.  6) Why can't I read / write the com ports?
  22.  7) What are interrupts and how to use them in Turbo Pascal?
  23.  8) Should I upgrade my Turbo Pascal version?
  24.  9) How do I execute an MsDos command from within a TP program?
  25. 10) How is millisecond timing done?
  26. 11) How can I customize the text characters to my own liking?
  27. 12) How to find the files in a directory and subdirectories?
  28. 13) I need a power function but there is none in Turbo Pascal.
  29. 14) How can I create arrays that are larger than 64 kilobytes?
  30. 15) How can I test that the printer is ready?
  31. 16) How can I clear the keyboard type-ahead buffer.
  32. 17) How can I utilize expanded memory (EMS) in my programs?
  33. 18) How can I obtain the entire command line?
  34. 19) How do I redirect text from printer to file in my TP program?
  35. 20) Turbo Pascal is for wimps. Use standard Pascal or C instead?
  36. 21) How do I turn the cursor off?
  37. 22) How to find all roots of a polynomial?
  38. 23) What is all this talk about "Pascal homework on the net"?
  39. 24) How can I link graphics drivers directly into my executable?
  40. 25) How can I trap a runtime error?
  41. 26) How to get ansi control codes working in Turbo Pascal writes?
  42. 27) How to evaluate a function given as a string to the program?
  43. 28) How does one detect whether input (or output) is redirected?
  44. 29) How does one set the 43/50 line text mode?
  45. 30) How can I assign a value to an environment variable in TP?
  46. -------------------------------------------------------------------
  47.  
  48. Unless otherwise stated the answers cover versions 4.0, 5.0, 5.5,
  49. 6.0 and 7.0 (real mode). The Q&As are not for Turbo Pascal version 3
  50. or earlier. Objects, TVision, or Windows are not covered. (I do not
  51. use them myself.)
  52.  
  53. From ts@uwasa.fi Wed Aug 18 00:00:01 1993
  54. Subject: Disabling or capturing the break key
  55.  
  56. 1. *****
  57.  Q: I don't want the Break key to be able to interrupt my TP
  58. programs. How is this done?
  59.  Q2: I want to be able to capture the Break key in my TP program.
  60. How is this done?
  61.  Q3: How do I detect if a certain key has been pressed?
  62.  
  63.  A: This very frequently asked question is basically a case of RTFM
  64. (read the f*ing manual). But this feature is, admittedly, not very
  65. prominently displayed in the Turbo Pascal reference. (As a general
  66. rule we should not use the newsgroups as a replacement for our
  67. possibly missing manuals, but enough of this line.)
  68.    There is a CheckBreak variable in the Crt unit, which is true by
  69. default. To turn if off use
  70.      uses Crt;
  71.      :
  72.      CheckBreak := false;
  73.      :
  74. Besides turning off break checking this enables you to capture the
  75. pressing of the break key as you would capture pressing ctrl-c. In
  76. other words you can use e.g.
  77.      :
  78. procedure TEST;
  79. var key : char;
  80. begin
  81.   repeat
  82.     if KeyPressed then
  83.       begin
  84.         key := ReadKey;
  85.         case key of
  86.           #3 : begin writeln ('Break'); exit; end;  {ctrl-c or break}
  87.           else write (ord(key), ' ');
  88.         end; {case}
  89.       end; {if}
  90.   until false;
  91. end;  (* test *)
  92.      :
  93. IMPORTANT: Don't test the ctrl-break feature just from within the TP
  94. IDE, because it has ctlr-break handler ("intercepter") of its own
  95. and may confuse you into thinking that ctrl-break cannot be
  96. circumvented by the method given above.
  97.   The above example has a double purpose. It also shows the
  98. rudiments how you can detect if a certain key has been pressed. This
  99. enables you to give input without echoing it to the screen, which is
  100. a later FAQ in this collection.
  101.   This is, however, not all there can be to break checking, since
  102. the capturing is possible only at input time. It is also possible to
  103. write a break handler to interrupt a TP program at any time. For
  104. more details see Ohlsen & Stoker, Turbo Pascal Advanced Techniques,
  105. Chapter 7.
  106. --------------------------------------------------------------------
  107.  
  108. From ts@uwasa.fi Wed Aug 18 00:00:02 1993
  109. Subject: Directing output also to printer
  110.  
  111. 2. *****
  112.  Q: I want to have a printed documentation of my students' Turbo
  113. Pascal program exercises. How is all input and output directed also
  114. to the printer?
  115.  
  116.  A1: Use a screen capturing program to put everything that comes
  117. onto the screen into a file, and print the file. See FAQPROGS.TXT in
  118. /pc/ts/tsfaqn37.zip (or whatever version number is the current) for
  119. more about these programs. Available by anonymous FTP or mail server
  120. from garbo.uwasa.fi.
  121.  
  122.  A2: See the code in TSPAS.NWS (item: Redirecting writes to the
  123. printer) in the /pc/ts/tspa33??.zip (or whatever is the current
  124. version number) Turbo Pascal units package (?? = 40, 50, 55, 60, or
  125. 70 depending on your TP version). Alternatively use USECON and
  126. USEPRN routines in the TSUNTG unit of the same package.
  127.  
  128.      +------------------------------------------+
  129.      ! To get these and other packages given as !
  130.      !   /dir/subdir/name                       !
  131.      ! see the instructions in PD2ANS.TXT       !
  132.      +------------------------------------------+
  133.  
  134.  A3: But the really elegant solution to the problem of getting a
  135. logfile (or a printed list) of a Turbo Pascal run is to rewrite the
  136. write(ln) and read(ln) device driver functions. In itself writing
  137. such driver redirections is very advanced Turbo Pascal programming,
  138. but when the programming has once been done, the system is extremely
  139. easy to use as many times as you like. It goes like this. The driver
  140. redirections are programmed into a unit (say, tpulog or tpuprn). All
  141. that is needed after that is to include the following uses statement
  142. into the program (the target program) which has to be logged:
  143.       uses TPULOG;    ( or )    uses TPUPRN;
  144. This is all there is to it. Just adding one simple line to the
  145. target program. (If you call any other units, "uses tpulog" must
  146. come AFTER the system units (eg Dos), but BEFORE any which you may
  147. define yourself!)
  148.    The reason that I have named two units here instead of just one
  149. in the above example is that the preferred log for the target
  150. program may be a logfile or the printer. The better solution of
  151. these two is to use the logfile option, and then print it. The
  152. reason is simple. If the target program itself prints something,
  153. your printout will look confused.
  154.    The logging also has obvious limitations. It works for standard
  155. input and output (read(ln) and write(ln)) only. 1) It does not
  156. support graphics, in other words it is for the textmode. 2) It does
  157. not support direct (Crt) screen writes. 3) And, naturally it only
  158. shows the input and output that comes to the screen. Not any other
  159. input or output, such as from or to a file. 4) Furthermore, you are
  160. not allowed to reassign input or output. Statements like assign
  161. (output, '') will result in a crash, because the rewritten output
  162. device redirections are invalidated by such statements. 5) The
  163. device on the default drive must not be write protected, since else
  164. the logfile cannot be written to it. 6) It does not work for Turbo
  165. Pascal 4.0. Despite these restrictions, the method is perfectly
  166. suited for logging students' Turbo Pascal escapades.
  167.    It is advisable first to test and run your target program without
  168. "tpulog", so that if you get any strange errors you'll know whether
  169. they are caused by the logging.
  170.    Where to get such a unit. The code can be found in Michael
  171. Tischer (1990), Turbo Pascal Internals, Abacus, Section 4.2. Next a
  172. few of my own tips on this unit Tischer calls Prot. 1) The code is
  173. in incorrect order. The code that is listed on pages 142 - 145 goes
  174. between pages 139 and 140. 2) You can change the logfile name (const
  175. prot_name) to lpt1 for a printed list of the target program run. In
  176. that case it is advisable to include a test for the online status of
  177. the printer within Tischer's unit. 3) I see no reason why the two
  178. lines in Tischer's interface section couldn't be transferred to the
  179. implementation section. Why have any global definitions?  But all in
  180. all, it works like magic!
  181.  
  182.  A4: From: abcscnuk@csunb.csun.edu (Naoto Kimura (ACM))
  183. Subject: Re: Printing a log of students' exercises revisited
  184. To: ts@uwasa.fi
  185. Date: Fri, 2 Nov 90 20:52:03 pdt
  186. [Reproduced with Naoto's kind permission]
  187. By the way, several months ago, I had submitted a file (nktools.zip)
  188. file on Simtel20 that contains sources to a unit (LOGGER), which
  189. allows logging of I/O going through the standard input and output
  190. files, while still being able to use the program interactively.  I
  191. believe that I also submitted a copy to your site.  It was something
  192. I put together for use by students here at California State
  193. University at Northridge.  The source works equally well in all
  194. presently available versions of Turbo Pascal.
  195. The only requirements are that
  196.  * you place it as one of the last entries in the USES clause.  If
  197.    there is anything that redirects the standard input and output
  198.    file variables, you should put that unit before my unit in the
  199.    USES clause, so that it can see the I/O stream.
  200.  * Don't use the GotoXY and similar screen display control
  201.    procedures in the Crt unit and expect it to come out the same way
  202.    you had it on the display.  Since all my unit does is just
  203.    capture the I/O stream to send it through the normal channels and
  204.    also to the log file, all screen control information is not sent
  205.    to the log file.
  206.  * All I/O you want logged should go through the standard input and
  207.    output file variables.
  208.  * Don't close the standard input and output file variables, because
  209.    it will cause problems.  Basically, as far as I have checked, it
  210.    just causes the logging to stop at that point.
  211. --------------------------------------------------------------------
  212.  
  213. From ts@uwasa.fi Wed Aug 18 00:00:03 1993
  214. Subject: Code to give the weekday of a date
  215.  
  216. 3. *****
  217.  Q: I want code that gives the weekday of the given date.
  218.  
  219.  A1: There is a WKDAYFN function in /pc/ts/tspa33*.zip (or whatever
  220. version number is the latest, and where * is 40 50 55 60 and 70)
  221. Turbo Pascal units collection to give the modern weekday based on
  222. Zeller's congruence. Available by anonymous FTP or mail server from
  223. garbo.uwasa.fi. Also you can find a more extensive Julian and
  224. Gregorian weekday algorithm with source code in Dr.Dobb's Journal,
  225. June 1989, p. 148. Furthermore Press & Flannery & al (1986),
  226. Numerical Recipes, Cambridge University Press, present a weekday
  227. code. The Numerical Recipes codes are available as
  228. /pc/turbopas/nrpas13.zip (big, 404k!).
  229.  
  230.  A2: Some will recommend the following kludge. Store the current
  231. date, change it, and let MsDos get you the weekday. Don't use it! It
  232. is a bad suggestion. On top of being sloppy programming, there are
  233. several snags.  The trick works only for years 1980-2079. A crash
  234. the program may leave the clock at a wrong date. And even if
  235. multitasking is rare, in a multitasking environment havoc may result
  236. for the other tasks. And you may have a TSR that requires the
  237. correct date, etc.
  238. --------------------------------------------------------------------
  239.  
  240. From ts@uwasa.fi Wed Aug 18 00:00:04 1993
  241. Subject: Pretty printers (or uniform code)
  242.  
  243. 4. *****
  244.  Q: Where can I find a program that formats my (or my students')
  245. Turbo Pascal code in a consistent matter.
  246.  
  247.  A: What you are asking for is often called "a pretty printer".
  248. TurboPower Software's (the usual disclaimer applies) commercial
  249. Turbo Analyst has a facility for this with many options. There are
  250. also PD and shareware pretty printers, such as /pc/turbopas/
  251. pritprn.zip, bp7sb*.zip "Source Beautifier for Borland Pascal by
  252. J.Ferincz", and others at garbo.uwasa.fi available by anonymous FTP
  253. or mail server. See /pc/INDEX.ZIP for a list of the files.
  254. --------------------------------------------------------------------
  255.  
  256. From ts@uwasa.fi Wed Aug 18 00:00:05 1993
  257. Subject: How to write TSR programs
  258.  
  259. 5. *****
  260.  Q: Can someone give me advice for writing a tsr program.
  261.  
  262.  A: Writing a terminate and stay resident program can be considered
  263. advanced programming and is beyond the scope of an electronic
  264. message with limited space. Instead, here are some references to
  265. Turbo Pascal books and papers which have a coverage of the subject.
  266. Stephen O'Brien, Turbo Pascal, The Complete Reference, Chapter 16;
  267. Stephen O'Brien, Turbo Pascal, Advanced Programmer's Guide, Chapter
  268. 6; Michael Tischer, Turbo Pascal Internals, Chapter 11 (a definite
  269. bible of TP programming!); Michael Yester, Using Turbo Pascal,
  270. Chapter 19; Kent Pottebaum, "Creating TSR Programs with Turbo
  271. Pascal", Dr. Dobb's Journal, May 1989 and June 1989; Kris Jamsa, Dos
  272. Power User's Guide, pp. 649-.
  273. --------------------------------------------------------------------
  274.  
  275. From ts@uwasa.fi Wed Aug 18 00:00:06 1993
  276. Subject: Programming com ports
  277.  
  278. 6. *****
  279.  Q: Why can't I read / write the com ports.
  280.  
  281.  A: Com port programming (most often writing telecommunication
  282. programs) is much much more complicated than simply trying to use
  283.   write (com, whatever);
  284.   read  (com, whatever);
  285. This is a very advanced subject (frankly, beyond me), and the best
  286. way to learn is to try to obtain some code to show you how. One
  287. place to look at is Turbo Pascal text-books (I have a long list of
  288. them at garbo.uwasa.fi archives in /pc/ts/tsfaqp*.zip. There also is
  289. an example by David Rind in garbo.uwasa.fi/pc/pd2/faquote.zip.
  290. Another source is International FidoNet pascal conference at some
  291. bulletin board near you. The conference has had some very good
  292. discussions in it.  (No, I don't have them stored for distribution,
  293. nor any further information.)
  294. --------------------------------------------------------------------
  295.  
  296. From ts@uwasa.fi Wed Aug 18 00:00:07 1993
  297. Subject: Primers to interrupt programming
  298.  
  299. 7. *****
  300.  Q: What are interrupts and how to use them in Turbo Pascal?
  301.  
  302.  A: An interrupt is a signal to the processor from a program, a
  303. hardware device, or the processor itself, to suspend temporarily
  304. what the program is doing, and to perform a routine that is stored
  305. in the operating system. There are 256 such interrupt routines, with
  306. many subservices stored in memory at locations, which are given in
  307. the so called interrupt table. Turbo Pascal (somewhat like C) has a
  308. special keyword Intr, and a predefined variable registers (in the
  309. Dos unit) to access these interrupt routines. One way of looking at
  310. them is as Turbo Pascal (complicated lowlevel) subroutines that are
  311. already there ready for you to call.
  312.    A detailed description of interrupt routines is way beyond a
  313. single message with limited space. Instead, I shall give a simple
  314. example, and good references to the subject. (For a somewhat more
  315. comprehensive description of what an interrupt is, see INTERRUP.PRI
  316. in Ralf Brown's garbo.uwasa.fi:/pc/programming/inter35b.zip.)
  317.      :
  318.      uses Dos;
  319.      (* This procedure turns on the border color for CGA and VGA *)
  320.      procedure BORDER (color : byte);
  321.      var regs : registers;  (* Predeclared in the Dos unit *)
  322.      begin
  323.        FillChar (regs, SizeOf(regs), 0);  (* A precaution *)
  324.        regs.ax := $0B00;    (* Service number *)
  325.        regs.bh := $00;      (* Subservice number *)
  326.        regs.bl := color;
  327.        Intr ($10, regs);    (* ROM BIOS video driver interrupt *)
  328.      end;  (* border *)
  329.    If you are new the subject and / or want ideas on the most useful
  330. interrupts in Turbo Pascal programming, Ben Ezzel (1989),
  331. Programming the IBM User Interface Using Turbo Pascal, is definitely
  332. the best reference to look at. There are also many other good
  333. references for a novice interrupt user, such as Jamsa & Nameroff,
  334. Turbo Pascal Programmer's Library.
  335.    If you are a more advanced interrupt user you'll find the
  336. following references very useful. Michael Tischer (1990), Turbo
  337. Pascal Internals; Norton & Wilton (1988), The New Peter Norton
  338. Programmer's guide to the IBM PC & PS/2; Ray Duncan (1988), Advanced
  339. MS-DOS Programming; Terry Dettmann (1989), Dos Programmer's
  340. Reference, Second edition, Que. Furthermore, there is an impressive
  341. list of interrupts collected and maintained by Ralf Brown. His
  342. extensive /pc/programming/inter35a.zip, inter35b.zip and
  343. inter35c.zip (or whatever are the current versions when you read
  344. this) is available by anonymous FTP or mail server from
  345. garbo.uwasa.fi. A definite must for an advanced user. Also see the
  346. reference to Brown's and Kyle's book in the bibliography at the end
  347. of this FAQ. Another useful (but in many respects a replicate) list
  348. is contained in the file /pc/programming/dosref22.zip (or, sigh,
  349. whatever is the current version). There is also a good hypertext
  350. advanced programmer's quick reference /pc/programming/helppc21.zip
  351. which you might find useful.
  352.    One more point for Turbo Pascal users. When Borland upgraded from
  353. version 3 to 4.0 quite a number of tasks that needed to be done
  354. using interrupts (such as getting the current time) were included as
  355. normal TP routines. This means that while definitely useful,
  356. interrupt programming is now relevant only in advanced Turbo Pascal
  357. programming. Turbo Pascal 5.0 introduced a few more, but you can
  358. find some of the missing TP 4.0 routines in the compatibility unit
  359. in my garbo.uwasa.fi:/pc/ts/tspa3340.zip TP units collection.
  360. --------------------------------------------------------------------
  361.  
  362. From ts@uwasa.fi Wed Aug 18 00:00:08 1993
  363. Subject: Borland's Turbo Pascal upgrades
  364.  
  365. 8. *****
  366.  Q: Should I upgrade my Turbo Pascal version?
  367.  
  368.  A1: Depends on what version you are using, and for what purposes.
  369. If you are using version 3, the answer is a definite yes. There are
  370. so many useful additions in the later version, including the concept
  371. of units, and a great number of new useful keywords. The only reason
  372. that I can think of for using TP 3 is that it makes .com files
  373. (which reside in one memory segment only) instead of .exe files. As
  374. an accounting and business finance teacher and researcher I've been
  375. somewhat surprised to see postings stating that some users still
  376. have to program in TP 3.0 because their employer doesn't want to
  377. take the cost of upgrading. I find this cost argument ridiculous.
  378. How about some consideration for cost effectiveness and
  379. productivity?
  380.    If you are currently using version 4.0, the most important point
  381. in considering upgrading is the integrated debugger in the later
  382. versions. It is really good, and useful if you write much code.
  383. There are some minor considerations, as well. Later versions contain
  384. some useful routines which 4.0 does not. I have programmed many of
  385. them to be available also for 4.0 in my /pc/ts/tspa3340.zip TO units
  386. collection (or whatever is the latest when you read this).
  387. Furthermore, I find somewhat annoying that the executables will
  388. always end up in the default directory.
  389.    If you are currently using version 5.0 the rational reasons for
  390. upgrading are needing objects, and a better overlay manager. I have
  391. also version 5.5 myself, but switched back to version 5.0 after I
  392. had some problems with its linking of object files. (This is a false
  393. statement from me, since it turned out that I had made a mistake
  394. myself. My thanks are due to bj_stedm@gould2.bristol-poly.ac.uk
  395. (Bruce Stedman) for questioning this item). Anyway, I don't use nor
  396. need OOP objects (don't confuse linking object files and object
  397. oriented programming here). One further point for 5.5. It has a
  398. better help function than 5.0, and a few more procedures and
  399. predefined constants. The TP 5.5 help includes examples, which can
  400. be even pasted into your program. This is handy.
  401.    The real snag in upgrading (waiving the reasonable cost) is the
  402. fact that the units of the different versions are incompatible. If
  403. you have a large library of units (as I do) you will have to
  404. recompile the lot. This is something that has caused a fair amount
  405. of justifiable flak against an otherwise excellent product.
  406.    A tip. Don't throw away your Turbo Pascal version 3.0 manual, if
  407. you have one. It is of use if you resort to the Turbo3 and Graph3
  408. compatibility units. They give you access e.g. to turtle graphics.
  409.    At the time of first writing this Turbo Pascal 6.0 version had
  410. just been announced. I didn't have it yet myself, but I had been
  411. (correctly) informed that its units are not compatible with the
  412. earlier versions. I now have Turbo Pascal 6.0, and I must say that
  413. my reactions have been disappointment and frustration. This is
  414. probably partly (but not entirely) my own fault, since Turbo Pascal
  415. seems to be headed from a common programming language into a full
  416. professional's specialized tool, with many features I don't know how
  417. to utilize. The only advancement from my point of view really is the
  418. multiple file editing, but I have long had alternative programs for
  419. that. If I used assembler (I don't) I am sure that I would find
  420. useful TP 6.0's potential to include assembler code as such instead
  421. of having to use the cumbersome Inline procedure of entering the
  422. assembler code.
  423.    There is also a Windows Turbo Pascal, as the latest addition to
  424. the plethora. Since I don't use Windows at all, I have no futher
  425. information on it.
  426.    I think a pattern is emerging here. Rather than being different
  427. versions of the same product, the consecutive Turbo Pascals are
  428. really different products for different purposes. Version 3.0 was a
  429. simple programming language. Version 4.0 extended it into a full
  430. scale programming modular platform. Version 5.0 introduced the
  431. debugger. And there an advanced hobbyist's path ended. Version 5.5
  432. introduced object oriented programming, which I'm sure is important
  433. for the initiated, but personally I just don't need it even if I
  434. write a lot of programs. And with the 6.0 we go completely out of
  435. the realm of conventional programming into Turbo Pascal visions.
  436. And Windows Turbo Pascal is for a different platform, altogether.
  437.    I find the new integrated user interface of TP 6.0 awkward in
  438. comparison to what was used in the 4.0, 5.0, and 5.5 versions. The
  439. IDE of TP leaves less free memory than the previous versions.
  440. Furthermore TP 6.0 IDE performs frequent disk accesses which cause
  441. slowdowns  making it virtually unusable from a floppy. And I
  442. wonder why Borland didn't at once go all the way to Windows, because
  443. that is what 6.0 really is. An intermediate, incomplete step in that
  444. direction. This means that we have a 5th upgrade in line with
  445. incompatible units. This is aggravating even for a TP fan, isn't it?
  446.    For information on Turbo Pascal version 7.0 and Borland email
  447. contact numbers see garbo.uwasa.fi:/pc/turbopas/bp7-info.zip. Also
  448. see bp7bugs*.zip by Duncan Murdoch. Turbo Pascal 7.0 or more
  449. extensively Borland Pascal 7.0 is a full professional's tool, and
  450. far beyond for example my moderate programming needs. To list only a
  451. few of the features are protected mode programming, handling of
  452. lagre programs, very fast compiling, and a daunting amount of
  453. matrial elboving away on one's disk space if one ever has the
  454. patience to look through it all. I would use the word
  455. "overwhelming". But for a serious programmer this is an impressive
  456. and a very worthwhile tool. One should not be misled skipping it
  457. because of my comments which were written from a hobbyist's point of
  458. view. As a general trend in programs, the well-known columnist John
  459. C. Dvorak calls this increasing product complexity trend "featurism"
  460. in PC Computing, May 1993.
  461.  
  462.  A2: From: dmurdoch@watstat.waterloo.edu (Duncan Murdoch),
  463. Newsgroups: comp.lang.pascal. Included with Duncan's kind
  464. permission. (Duncan is one of the most knowledgeable and useful
  465. contributors to the comp.lang.pascal UseNet newsgroup).
  466.    One other reason:  there's a bug in the code generator for 4.0
  467. and 5.0 that makes it handle the Extended (10 byte) real type
  468. poorly.  The code generated makes very poor use of the 8 element
  469. internal stack on the coprocessor, so that expressions with lots of
  470. operands like
  471.   e1+e2+e3+e4+e5+e6+e7+e8+e9
  472. always fail, if all the e's are of type extended.  (The generated
  473. code pushes each operand onto the stack, then does all the adds.
  474. It's smarter to push and add them one at a time.)
  475.    This makes it a real pain translating numerical routines from
  476. Fortran, especially since constants are taken to be of type
  477. extended.
  478.    The bug was fixed in 5.5.
  479.  
  480.  A3: From: Bengt Oehman (d92bo@efd.lth.se): A difference between
  481. v4.0 and v5.5 is that you can calculate constants in tp55, but not
  482. in 4.0. I see this as a big advantage. For example:
  483.   CONST MaxW = 10;
  484.         MaxH = 20;
  485.         MaxSize = MaxW*MaxH;
  486.         { or }
  487.         MaxX = 100;
  488.         HalfMaxX = MaxX DIV 2;
  489. cannot be compiled with 4.0.
  490. --------------------------------------------------------------------
  491.  
  492. From ts@uwasa.fi Wed Aug 18 00:00:09 1993
  493. Subject: Shelling from a TP program
  494.  
  495. 9. *****
  496.  Q: How do I execute an MsDos command from within a TP program?
  497.  
  498.  A: The best way to answer this question is to give an example.
  499.      {$M 2048, 0, 0}   (* <-- Important *)
  500.      program outside;
  501.      uses dos;
  502.      begin
  503.        write ('Directory call from within TP by Timo Salmi');
  504.        SwapVectors;
  505.        Exec (GetEnv('comspec'), '/c dir *.*');  (* Execution *)
  506.        SwapVectors;
  507.        (* Testing for errors is recommended *)
  508.        if DosError <> 0 then
  509.          writeln ('Dos error number ', DosError)
  510.        else
  511.          writeln ('Mission accomplished, exit code ', DosExitCode);
  512.        (* For DosError and DosExitCode details see the TP manual *)
  513.      end.
  514. Alternatively, take a look at execdemo.pas from demos.arc which
  515. is on the accompanying Turbo Pascal disk.
  516.    What the above Exec does is that it executes the command
  517. processor. The /c specifies that the command interpreter is to
  518. perform the command, and then stop (not halt).
  519.    I have also seen it asked how one can swap the Turbo Pascal
  520. program to the disk when shelling. It is unnecessary to program that
  521. separately because there is an excellent program to do that for you.
  522. It is garbo.uwasa.fi:/pc/sysutil/shroom2d.zip.
  523. --------------------------------------------------------------------
  524.  
  525. From ts@uwasa.fi Wed Aug 18 00:00:10 1993
  526. Subject: Millisocond timing
  527.  
  528. 10. *****
  529.  Q: How is millisecond timing done?
  530.  
  531.  A: A difficult task, but the facilities are readily available.
  532. TurboPower Software's commercial Turbo Professional (don't confuse
  533. with Borland's Turbo Professional) has a unit for this. (The usual
  534. disclaimer applies). This one has been released to the PD. It is
  535. called tptimer and is part of the /pc/turbopas/bonus507.zip package.
  536. I have also seen a SIMTEL20 upload announcement of a ztimer11.zip
  537. for C and ASM, but I have no further information on that. Another
  538. option is /pc/turbopas/qwktimer.zip. It is not quite as accurate as
  539. tptimer.
  540.    To test the tptimer unit in bonus507.zip you can use the
  541. following example code
  542.   uses Crt, tptimer;
  543.   var time1, time2 : longint;
  544.   begin
  545.     InitializeTimer;
  546.     time1 := ReadTimer;
  547.     Delay (1356);    (* Or whatever code you wish to benchmark *)
  548.     time2 := ReadTimer;
  549.     RestoreTimer;
  550.     writeln ('Elapsed = ', ElapsedTime (time1, time2)/1000.0 : 0 : 3);
  551.   end.
  552.    It is quite another question when you really need the millisecond
  553. timing. The most common purpose for millisecond timing is testing
  554. the efficiency of alternative procedures and functions, right? The
  555. way I compare mine is simple. I call the procedures or functions I
  556. want to compare for speed, say, a thousand times in a loop.  And
  557. test this for elapsed time. This way the normal resolution (18.2
  558. cycles per second) of the system clock becomes sufficient. This is
  559. accurate enough for the comparisons.
  560.      var elapsed : real; i : word;
  561.      elapsed := TIMERFN;  (* e.g. from /pc/ts/tspa3355.zip *)
  562.      for i := 1 to 1000 do YOURTEST;  (* Try out the alternatives *)
  563.      elapsed := TIMERFN - elapsed;
  564.      writeln ('Elapsed : ', elapsed : 0 : 2);
  565. Incidentally, if you want to make more elaborate evaluations of the
  566. efficiency of your code, Borland's Turbo Profiler is a useful tool.
  567. (The usual disclaimer naturally applies.)
  568. --------------------------------------------------------------------
  569.  
  570. From ts@uwasa.fi Wed Aug 18 00:00:11 1993
  571. Subject: Text font customizing
  572.  
  573. 11. *****
  574.  Q: How can I customize the text characters to my own liking?
  575.  
  576.  A: As far as I know, text-mode characters are hard-coded, and
  577. cannot be customized at all unless you have an EGA or VGA adapter.
  578. But you can always retrieve the bitmap information for the ascii
  579. characters from your PC.
  580.    The bitmap table for the lower part of the character set (0-127)
  581. starts at memory position $F000 and ends at $FA6E. The upper part is
  582. not at a fixed memory location. The pointer to the memory address of
  583. upper part of the ascii table (provided that graftabl has been
  584. loaded) is at an address $007C. One way of saying this is that the
  585. segment address of the upper part's memory location is at $007E, and
  586. its offset at $007C.
  587.    Going into more details is beyond the scope of this posting. If
  588. you want more information see Kent Porter (1987), Stretching Turbo
  589. Pascal, Chapter 12, and Kent Porter & Mike Floyd (1990), Stretching
  590. Turbo Pascal. Version 5.5. Revised Edition. Brady, Chapter 11.
  591.    If you are interested in a demonstration of utilizing the
  592. bitmapped character information (no source code available), take a
  593. look at the demo in the garbo.uwasa.fi anonymous FTP archives file
  594. /pc/ts/tsdemo15.zip (or whatever version number is current).
  595.    Turbo Pascal also supports what is called stroked fonts (the
  596. .chr) files which draw characters instead of bitmapping them. The
  597. user should be able to write one's own .chr definitions, but I have
  598. no experience nor information on how this can be done.
  599.    There is something called bgikit10.zip which has facilities for
  600. making fonts and adding graphics drivers. The problem is that I
  601. cannot make it publicly available, since I think that it is not PD.
  602. I am still missing the information. Unfortunately, it is not even
  603. the only case where I encountered the fact that Borland does not
  604. seem at all interested in the UseNet users' queries about the status
  605. and distributability of their material.
  606.    (From Leonard Erickson Leonard.Erickson@f51.n105.z1.fidonet.org
  607. Well, you can *also* do it if you have a Hercules Graphics Card Plus
  608. or Hercules InColor card (as far as I know, the only cards that
  609. implemented Hercules RamFont 'standard'). And you can modify the
  610. upper 128 characters on a CGA card. BTW, the RamFont cards are
  611. *nice* pity it appeared too late to become a standard. It's a *lot*
  612. more flexible than EGA/VGA fonts (I can have several *dozen* fonts
  613. resident).)
  614. --------------------------------------------------------------------
  615.  
  616. From ts@uwasa.fi Wed Aug 18 00:00:12 1993
  617. Subject: Finding files in TP
  618.  
  619. 12. *****
  620.  Q: How to find the files in a directory AND subdirectories?
  621.  
  622.  A: Writing a program that goes through the files of the directory,
  623. and all the subdirectories below it, is based on Turbo Pascal's file
  624. finding commands and recursion. This is universal whether you are
  625. writing, for example, a directory listing program, or a program that
  626. deletes, say, all the .bak files, or some other similar task.
  627.    To find (for listing or other purposes) the files in a directory
  628. you need above all the FindFirst and FindNext keywords, and testing
  629. the predefined file attributes. You make these a procedure, and call
  630. it recursively. If you want good examples with source code, please
  631. see PC World, April 1989, p. 154; Kent Porter & Mike Floyd (1990),
  632. Stretching Turbo Pascal. Version 5.5. Revised Edition. Brady,
  633. Chapter 23; and Michael Yester (1989), Using Turbo Pascal, p. 437;
  634. dirtree.pas in /pc/pcmag/vol8n01.zip.
  635.    The simple (non-recursive) example listing all the read-only
  636. files in the current directory shows the rudiments of the principle
  637. of Using FindFirst, FindNext, and the file attributes, because some
  638. users find it hard to use these keywords.
  639.     uses Dos;
  640.     var FileInfo : SearchRec;
  641.     begin
  642.       FindFirst ('*.*', AnyFile, FileInfo);
  643.       while DosError = 0 do
  644.         begin
  645.           if (FileInfo.Attr and ReadOnly) > 0 then
  646.             writeln (FileInfo.Name);
  647.           FindNext (FileInfo);
  648.         end;
  649.     end.  (* test *)
  650.  
  651.  A2: While we are on the subject related to FindFirst and FindNext,
  652. here are two useful examples:
  653.  
  654. (* Number of files in a directory (not counting directories) *)
  655. function DFILESFN (dirName : string) : word;
  656. var nberOfFiles  : word;
  657.     FileInfo     : searchRec;
  658. begin
  659.   if dirName[Length(dirName)] <> '\' then dirName := dirName + '\';
  660.   dirName := dirName + '*.*';
  661.   {}
  662.   nberOfFiles := 0;
  663.   FindFirst (dirName, AnyFile, FileInfo);
  664.   while DosError = 0 do
  665.     begin
  666.       if ((FileInfo.Attr and VolumeId) = 0) then
  667.         if (FileInfo.Attr and Directory) = 0 then
  668.           Inc (nberOfFiles);
  669.       FindNext (FileInfo);
  670.     end; {while}
  671.   dfilesfn := nberOfFiles;
  672. end;  (* dfilesfn *)
  673.  
  674. (* Number of immediate subdirectories in a directory *)
  675. function DDIRSFN (dirName : string) : word;
  676. var nberOfDirs : word;
  677.     FileInfo    : searchRec;
  678. begin
  679.   if dirName[Length(dirName)] <> '\' then dirName := dirName + '\';
  680.   dirName := dirName + '*.*';
  681.   {}
  682.   nberOfDirs:= 0;
  683.   FindFirst (dirName, AnyFile, FileInfo);
  684.   while DosError = 0 do
  685.     begin
  686.       if ((FileInfo.Attr and VolumeId) = 0) then
  687.         if (FileInfo.Attr and Directory) > 0 then
  688.           if (FileInfo.Name <> '.') and (FileInfo.Name <> '..') then
  689.             Inc (nberOfDirs);
  690.       FindNext (FileInfo);
  691.     end; {while}
  692.   ddirsfn := nberOfDirs;
  693. end;  (* ddirsfn *)
  694. --------------------------------------------------------------------
  695.  
  696. From ts@uwasa.fi Wed Aug 18 00:00:13 1993
  697. Subject: A generic power function code for TP
  698.  
  699. 13. *****
  700.  Q: I need a power function but there is none in Turbo Pascal.
  701.  
  702.  A: Pascals do not have an inbuilt power function. You have to write
  703. one yourself. The common, but non-general method is defining
  704.    function POWERFN (number, exponent : real) : real;
  705.      begin
  706.        powerfn := Exp(exponent*Ln(number));
  707.      end;
  708. To make it general use:
  709.    (* Generalized power function by Prof. Timo Salmi *)
  710.    function GENPOWFN (number, exponent : real) : real;
  711.    begin
  712.      if (exponent = 0.0) then
  713.        genpowfn := 1.0
  714.      else if number = 0.0 then
  715.        genpowfn := 0.0
  716.      else if abs(exponent*Ln(abs(number))) > 87.498 then
  717.        begin writeln ('Overflow in GENPOWFN expression'); halt; end
  718.      else if number > 0.0 then
  719.        genpowfn := Exp(exponent*Ln(number))
  720.      else if (number < 0.0) and (Frac(exponent) = 0.0) then
  721.        if Odd(Round(exponent)) then
  722.          genpowfn := -GENPOWFN (-number, exponent)
  723.        else
  724.          genpowfn :=  GENPOWFN (-number, exponent)
  725.      else
  726.        begin writeln ('Invalid GENPOWFN expression'); halt; end;
  727.    end;  (* genpowfn *)
  728. --------------------------------------------------------------------
  729.  
  730. From ts@uwasa.fi Wed Aug 18 00:00:14 1993
  731. Subject: Arrays > 64K
  732.  
  733. 14. *****
  734.  Q: How can I create arrays that are larger than 64 kilobytes?
  735.  
  736.  A: Turbo Pascal does not directly support the so-called huge arrays
  737. but you can get by this problem with a clever use of pointers as
  738. presented in Kent Porter, "Handling Huge Arrays", Dr.Dobb's Journal,
  739. March 1988. In this method you point to an element of a two
  740. dimensional array using a^[row].col^[column]. The idea involves too
  741. much code and explanation to be repeated here, so you'll have to see
  742. the original reference. But I know from my own experience, that the
  743. code works like magic. (The code is available from garbo.uwasa.fi
  744. archives as /pc/turbopas/ddj8803.zip). Kent Porter, "Huge Arrays
  745. Revisited", Dr.Dobb's Journal, October 1988, presents the extension
  746. of the idea to huge virtual arrays. (Virtual arrays mean arrays that
  747. utilize disk space).
  748.    Another possibility is using TurboPower Software's (the usual
  749. disclaimer applies) commercial Turbo Professional (don't confuse
  750. with Borland's Turbo Professional) package. It has facilities for
  751. huge arrays, but they involve much more overhead than Kent Porter's
  752. excellent method.
  753.  
  754. (* =================================================================
  755.    My code below is based on a UseNet posting in comp.lang.pascal
  756.    by Naji Mouawad nmouawad@watmath.waterloo.edu. Naji's idea was
  757.    for a vector, my adaptation is for a two-dimensional matrix. The
  758.    realization of the idea is simpler than the one presented by Kent
  759.    Porter in Dr.Dobb's Journal, March 1988. (Is something wrong,
  760.    this is experimental.)
  761.    ================================================================= *)
  762.    {}
  763.    const maxm = 150;
  764.          maxn = 250;
  765.    {}
  766.    type BigVectorType = array [1..maxn] of real;
  767.         BigMatrixType = array [1..maxm] of ^BigVectorType;
  768.    {}
  769.    var BigAPtr : BigMatrixType;
  770.    {}
  771.    (* Create the dynamic variables *)
  772.    procedure MAKEBIG;
  773.    var i          : word;
  774.        heapNeeded : longint;
  775.    begin
  776.      heapNeeded := maxm * maxn * SizeOf(real) + maxm * 4 + 8196;
  777.      if (MaxAvail <= heapNeeded) then
  778.        begin writeln ('Out of memory'); halt; end;
  779.      for i := 1 to maxm do New (BigAPtr[i]);
  780.    end;  (* makebig *)
  781.    {}
  782.    (* Test that it works *)
  783.    procedure TEST;
  784.    var i, j : word;
  785.    begin
  786.      for i := 1 to maxm do
  787.        for j := 1 to maxn do
  788.          BigAPtr[i]^[j] := i * j;
  789.      {}
  790.      writeln (BigAPtr[5]^[7] : 0:0);
  791.      writeln (BigAPtr[maxm]^[maxn] : 0:0);
  792.    end;  (* test *)
  793.    {}
  794.    (* The main program *)
  795.    begin
  796.      writeln ('Big arrays test by Prof. Timo Salmi, Vaasa, Finland');
  797.      writeln;
  798.      MAKEBIG;
  799.      TEST;
  800.    end.
  801. (For a better test of the heap than in MAKEBIG see Swan (1989), pp.
  802. 462-463.)
  803. --------------------------------------------------------------------
  804.  
  805. From ts@uwasa.fi Wed Aug 18 00:00:15 1993
  806. Subject: Testing printer status
  807.  
  808. 15. *****
  809.  Q: How can I test that the printer is ready?
  810.  
  811.  A: The usually advocated method in Turbo Pascal is to test the
  812. status of regs.ah after a call to interrupt 17 Hex (the parallel
  813. port driver interrupt), service 02:
  814.       regs.dx := PrinterNumber;  (* LPT1 = 0 *)
  815.       regs.ah := $02;            (* var regs : registers, uses DOS *)
  816.       Intr ($17,regs);           (* Interrupt 17 Hex *)
  817.       status := regs.ah          (* var status : byte *)
  818. But this is not a good method since the combinations of the status
  819. bits which indicate a ready state can vary from printer to printer
  820. and PC to PC. If you want a list of the status bits, see eg Ray
  821. Duncan (1988), Advanced MS-DOS Programming, p. 587. For an example
  822. of a code using interrupt 17 Hex see Douglas Stivison (1986), Turbo
  823. Pascal Library, pp. 118-120. Also see Michael Yester (1989), Using
  824. Turbo Pascal, pp. 494-495.
  825.    The more generic alternative is to try to write a #13 to the
  826. printer having the i/o checking off, that is, while {$I-} is in
  827. effect, and testing the IOResult. But then you must first alter the
  828. printer retry times default (and restore it afterwards). Else the
  829. method can take up to a minute instead of an immediate response.
  830. Also, you must have set the FileMode for LPT1 appropriately (and
  831. restore it afterwards). Sounds a bit complicated, but you don't have
  832. to do all this yourself. There is a boolean function "LPTONLFN Get
  833. the online status of the first parallel printer" for this purpose in
  834. my /pc/ts/tspa33??.zip (or whatever version number is the latest)
  835. Turbo Pascal units collection available by anonymous FTP or mail
  836. server from garbo.uwasa.fi.
  837. --------------------------------------------------------------------
  838.  
  839. From ts@uwasa.fi Wed Aug 18 00:00:16 1993
  840. Subject: Clearing the keyboard buffer
  841.  
  842. 16. *****
  843.  Q: How can I clear the keyboard type-ahead buffer.
  844.  
  845.  A: Three methods are usually suggested for solving this problem.
  846. a) The first is to use something like
  847.      uses Crt;
  848.      var dummy : char;
  849.      while KeyPressed do dummy := ReadKey;
  850. This kludge-type method has the disadvantage of requiring the Crt
  851. unit. Also, in connection with procedures relying on ReadKey for
  852. input, it may cause havoc on the programs logic.
  853. b) The second method accesses directly the circular keyboard buffer
  854.      var head : word absolute $0040:$001A;
  855.          tail : word absolute $0040:$001C;
  856.      procedure FLUSHKB; begin head := tail; end;
  857. c) The third method is to call interrupt 21Hex (the MsDos interrupt)
  858. with the ax register set as $0C00. This method has the advantage of
  859. not being "hard-coded" like the second method, and thus should be
  860. less prone to incompatibility.
  861. --------------------------------------------------------------------
  862.  
  863. From ts@uwasa.fi Wed Aug 18 00:00:17 1993
  864. Subject: Utilizing expanded memory
  865.  
  866. 17. *****
  867.  Q: How can I utilize expanded memory (EMS) in my programs?
  868.  
  869.  A: I have no experience (yet?) on this subject myself, but I can
  870. give you a list of references: Michael Tischer (1990), Turbo Pascal
  871. Internals, Abacus, Chapter 9; Stephen O'Brien (1988), Turbo Pascal,
  872. Advanced Programmer's Guide, Borland-Osborne, Chapter 4; Chris
  873. Ohlsen & Gary Stoker (1989), Turbo Pascal Advanced Techniques, Que,
  874. Chapter 11, and, maybe most importantly, Dorfman & Neuberger, Turbo
  875. Pascal Memory Management Techniques (with lots of code).
  876.    Furthermore, Turbo Pascal delivery disks (at least 5.0) contain a
  877. demos.arc archive which includes a ems.pas file.
  878. --------------------------------------------------------------------
  879.  
  880. From ts@uwasa.fi Wed Aug 18 00:00:18 1993
  881. Subject: Capturing the entire command line
  882.  
  883. 18. *****
  884.  Q: How can I obtain the entire command line (spaces and all)?
  885.  
  886.  A: ParamCount and ParamStr are for parsed parts of the command line
  887. and cannot be used to get the command line exactly as it was. See
  888. what happens if you try to capture
  889.   "Hello.   I'm here"
  890. you'll end up with a false number of blanks. For obtaining the
  891. command line unaltered use
  892.   type CommandLineType = string[127];
  893.   var  CommandLinePtr  : ^CommandLineType;
  894.   begin
  895.     CommandLinePtr := Ptr(PrefixSeg, $80);
  896.     writeln (CommandLinePtr^);
  897.   end;
  898. A warning. If you want to get this correct (the same goes for TP's
  899. own ParamStr and ParamCount) apply them early in your program. At
  900. least they must be used before any disk I/O takes place!
  901. --------------------------------------------------------------------
  902.  
  903. From ts@uwasa.fi Wed Aug 18 00:00:19 1993
  904. Subject: Redirecting from printer to file
  905.  
  906. 19. *****
  907.  Q: How do I redirect text from printer to file in my TP program?
  908.  
  909.  A: Simple. This is done in Turbo Pascal by using the assign command
  910. (think what the word 'assign' implies). Here is a simple example of
  911. the idea.
  912.   uses Printer;
  913.   begin
  914.     assign (lst, 'printer.log');
  915.     rewrite (lst);
  916.     writeln (lst, 'Hello world');
  917.     close (lst);
  918.   end.
  919. --------------------------------------------------------------------
  920.  
  921. From ts@uwasa.fi Wed Aug 18 00:00:20 1993
  922. Subject: Turbo Pascal users are just wimps
  923.  
  924. 20. *****
  925.  Q: Turbo Pascal is for wimps. Why don't you use standard Pascal or
  926. better still why don't you use C?
  927.  
  928.  A: These kinds of "real-programmers" statements often reflect what
  929. is called self-over-others attitude, and they are a part of a kind
  930. of a programming lore or cult. Basically, these attitudes waive the
  931. simple fact that one should select one's tools according to the task
  932. at hand, not vice versa. On the other hand one's productivity is
  933. usually best when being able to use tools which one is familiar and
  934. comfortable with. (Note however that the real-programmer's lore is
  935. not really interested in producing results.)
  936.    In very rough terms there are two attitudes to programming
  937. languages. They can be seen as tools for writing applications, or
  938. (by surprisingly many) as ends themselves.
  939.    If we first look at standard Pascal (versus Turbo Pascal),
  940. considering the language primary and its usage secondary is common.
  941. This results from the history of Pascal, since as we all know it was
  942. originally meant as a means for teaching programming concepts, not
  943. at all for writing applications. But because Pascal turned out to be
  944. useful also for writing applications, it has been extended for some
  945. operating systems, most notably MsDos (Turbo Pascal) and VAX/VMS
  946. (VAX Pascal). Both remedy a lot of flaws from the application
  947. programmer's point of view. Most notably they have a true file I/O
  948. interface, and enhanced string handling. Turbo Pascal (the more
  949. generic of these two) clearly draws from the structure and ideas of
  950. advanced BASICs (and vice versa). While in standard Pascal the
  951. language is an end by itself, for Turbo Pascal the only relevant
  952. issue is its usefulness for writing applications.
  953.    One problem that one encounters when moving away from standard
  954. Pascal is the problem of portability. This is a truly serious
  955. problem, since most often extensive rewriting is necessary from
  956. converting say a Turbo Pascal to, say, Unix Pascal. I have taken
  957. Unix Pascal as the extreme example, since Unix Pascal in almost
  958. nothing but the standard Pascal having no useful file I/O.
  959.    If one considers C, its best aspect from applications point of
  960. view is portability, and its strength for system programming. But it
  961. is not an easy language to learn. Proponents of C also often have
  962. the tendency discussed above, that is seeing the language as
  963. primary, and its utilization as secondary. Now why this tendency,
  964. not only for C, but in general? I've had the opportunity of writing
  965. programs starting from the late 1960's, and one observation I have
  966. made, and often propounded the view is that it is not writing code
  967. that is the really difficult part. What is really difficult it is
  968. coming up with good and original ideas for programs to write. I see
  969. applications as primary, and the tools as secondary. As to Turbo
  970. Pascal, I've written in many languages (including Cobol, Fortran,
  971. several Basics and Pascals, and command languages) and I like Turbo
  972. Pascal because it is one of the most convenient and flexible tools
  973. for writing the kind of applications that I usually write and
  974. distribute for the Public Domain. That is I use Turbo Pascal because
  975. I'm comfortable with it in writing applications, and have thus
  976. gathered a very useful modular libary for it over the years, not
  977. because of any inherent value attached to Turbo Pascal per se.
  978.  
  979.  A2: Another, a somewhat resembling line is made up by the arguments
  980. about standards in Pascal which are recycled in comp.lang.pascal
  981. time after time. Very often they end up with purists vs pragmatists
  982. arguing about the true or imaginary viles of using GOTOs. I find all
  983. this somewhat futile, although I understand the academic nature of
  984. the background. As you'll recall, Pascal was first developed for
  985. academic teaching programming concepts, not for any practical
  986. programming. That came later, and the ensuing popularity of Pascal
  987. in practical applications must have come as a surprise way back
  988. then. I admit being biased in not symphatizing with Pascal standard
  989. stalwarts. I am far more interested in getting the job done than in
  990. defending a barren orthodoxy.
  991. --------------------------------------------------------------------
  992.  
  993. From ts@uwasa.fi Wed Aug 18 00:00:21 1993
  994. Subject: Turning off the cursor
  995.  
  996. 21. *****
  997.  Q: How do I turn the cursor off?
  998.  
  999.  A: The usually advocated trick for turning the cursor off is to
  1000. equate the lower and the upper scan line of the cursor as explained
  1001. eg in Stephen O'Brien (1988), Turbo Pascal, Advanced Programmer's
  1002. Guide.
  1003.      uses Dos;
  1004.      var regs : registers;
  1005.      begin
  1006.        regs.ax := $0100;   (* Service $01 *)
  1007.        regs.cl := $20;     (* Top scan line *)
  1008.        regs.ch := $20;     (* Botton scan line *)
  1009.        Intr ($10, regs);   (* ROM BIOS video driver interrupt *)
  1010.      end;
  1011. To turn the cursor back on this (and many other) sources suggest
  1012. setting regs.ch and regs.cl as 12 and 13 for mono screen, and 6 and
  1013. 7 for others.
  1014.    This is not a good solution since it is equipment dependent, and
  1015. may thus produce unexcepted results. Better to store the current
  1016. scan line settings, and turn off the cursor bit. Below is the code
  1017. from my Turbo Pascal units collection /pc/ts/tspa33??.zip (or
  1018. whatever version number is the latest) available by anonymous FTP
  1019. from garbo.uwasa.fi archives. The general idea is that regs.ch bit 5
  1020. toggles the cursor on / off state. Thus to set the cursor off, apply
  1021.   regs.ch := regs.ch or $20;    (* $20 = 00100000 *)
  1022. and to set it on, apply
  1023.   regs.ch := regs.ch and $DF;   (* $DF = 11011111 *)
  1024. (* From TSUNTE unit, which also has a CURSON procedure *)
  1025. procedure CURSOFF;
  1026. var regs : registers;
  1027. begin
  1028.   FillChar (regs, SizeOf(regs), 0);  (* Initialize, a precaution *)
  1029.   {... find out the current cursor size (regs.ch, regs.cl) ...}
  1030.   regs.ah := $03;
  1031.   regs.bh := $00;    (* page 1, superfluous because of FillChar *)
  1032.   Intr ($10, regs);  (* ROM BIOS video driver interrupt *)
  1033.   {... turn off the cursor without changing its size ...}
  1034.   regs.ah := $01;                   (* Below are bits 76543210 *)
  1035.   regs.ch := regs.ch or $20;  (* Turn on bit 5; $20 = 00100000 *)
  1036.   Intr ($10, regs);
  1037. end;  (* cursoff *)
  1038.  
  1039.  A2: Another solution that has been suggested is putting the cursor
  1040. outside the screen using the GoToXY procedure. Fair enough, but then
  1041. you need to use the Crt unit, which is not always desirable.
  1042. Besides, how do you write on the screen if the cursor postion is off
  1043. it?
  1044.  
  1045.  A3: (Not to be taken seriously). Simple, turn off your computer and
  1046. the cursor stops showing :-).
  1047. --------------------------------------------------------------------
  1048.  
  1049. From ts@uwasa.fi Wed Aug 18 00:00:22 1993
  1050. Subject: Finding the roots of a polynomial
  1051.  
  1052. 22. *****
  1053.  Q: How to find all roots of a polynomial?
  1054.  
  1055.  A: If you need the code, see Turbo Pascal Numerical Toolbox and/or
  1056. Press & Flannery & Teukolsky & Vetterling (1986), Numerical Recipes,
  1057. The Art of Scientific Computing, Cambridge University Press. The
  1058. Numerical Recipes codes are available as /pc/turbopas/nrpas13.zip
  1059. (big, 404k!). If you just need to solve such a task (without code
  1060. available), get /pc/ts/tsnum12.zip (or whatever version number is
  1061. the latest) from garbo.uwasa.fi archives by anonymous FTP or mail
  1062. server.
  1063. --------------------------------------------------------------------
  1064.  
  1065. From ts@uwasa.fi Wed Aug 18 00:00:23 1993
  1066. Subject: Pascal homework on the net
  1067.  
  1068. 23. *****
  1069.  Q: What is all this talk about "Pascal homework on the net"?
  1070.  
  1071.  A: This is one of the subjects that seems to pop up at regular
  1072. intervals, cause some heated exchange for awhile, and then die down
  1073. again leaving some users harboring warranted or unwarranted grudges.
  1074.    Some posters to comp.lang.pascal have been very concerned of the
  1075. possibility that the questions posed on the net are related to
  1076. students' homework assignments. I don't have any unequivocal answers
  1077. or a clearcut stand on this question, just some comments.
  1078.    The most important task of a newsgroup like comp.lang.pascal is
  1079. the exchange of information between the users. If you think that
  1080. what you are going to post is interesting and useful to the group,
  1081. that should be your topmost criterion.
  1082.    If it is really a student that wants his/her work done on the net
  1083. (how do we know anyway?) also consider the following fact. Being
  1084. able to use a newsgroup amounts to having learned at least something
  1085. about using computers, and that is something per se.
  1086.    Even if the student may short-sightedly not see it, providing ALL
  1087. the code for a student's homework is detrimental to the student,
  1088. since it is she/he that foregoes understanding what he/she is doing.
  1089. The group should not condone outright cheating. Being (partly) a
  1090. teacher myself, I understand also this view.
  1091.    If a student is stuck with a problem in his/her code, I don't see
  1092. any real harm in helping out, especially if the problem has general
  1093. interest. Instructing is what teaching is about, anyway, isn't it?
  1094.    But, on the other hand, I must admit that I find a it rather
  1095. flagrant if a posting asks for something of the kind "I have to
  1096. complete my term assignment to write a function plotter by the end
  1097. of this month. Send me the code, since I'm too busy with my other
  1098. exams to write it myself" (a true quote).
  1099.    Finally, let's not jump to premature conclusions about anyone's
  1100. questions.  That's what most often triggers off a vicious circle of
  1101. flaming.
  1102. --------------------------------------------------------------------
  1103.  
  1104. From ts@uwasa.fi Wed Aug 18 00:00:24 1993
  1105. Subject: Linking bgi drivers into executables
  1106.  
  1107. 24. *****
  1108.  Q: How can I link graphics drivers directly into my executable?
  1109.  
  1110.  A: This is a complicated, yet a very useful task, because then you
  1111. won't need any separate graphics drivers (or fonts) to go separately
  1112. along with your program. Unfortunately, Turbo Pascal documentation
  1113. on this task is a bit confusing.
  1114.    1) The very first step is to get the necessary files from the
  1115. Turbo Pascal disks to your working directory. To start with, you'll
  1116. need binobj.exe and all the .bgi files.
  1117.    2) Run the following commands (best to place them in a batch,
  1118. call it eg makeobj.bat):
  1119.      binobj cga.bgi cga CGADriverProc
  1120.      binobj egavga.bgi egavga EGAVGADriverProc
  1121.      binobj herc.bgi herc HercDriverProc
  1122.      binobj pc3270.bgi pc3270 PC3270DriverProc
  1123.      binobj att.bgi att ATTDriverProc
  1124.      rem binobj ibm8514.bgi 8514 IBM8514DriverProc
  1125.    3) Get drivers.pas from the Turbo Pascal disk and compile it with
  1126. Turbo Pascal. Now you have a drivers.tpu unit which contains all the
  1127. graphics drivers.
  1128.    4) Now you won't need the .bgi and the .obj files any more. You
  1129. may delete them from your working directory.
  1130.    5) Write your graphics program in the usual manner. But before
  1131. putting your program in the graphics mode use the following
  1132. procedure if you want to link e.g. the EGAVGA graphics driver
  1133. directly into your executable. (Link just the driver(s) you'll need,
  1134. since the drivers take up a lot of space.)
  1135.      uses Graph, Drivers;
  1136.      :
  1137.      procedure EGAVGA2EXE;
  1138.      begin
  1139.        if RegisterBGIdriver(@EGAVGADriverProc) < 0 then
  1140.          begin
  1141.            writeln ('EGA/VGA: ', GraphErrorMsg(GraphResult));
  1142.            halt(1);
  1143.          end;
  1144.      end; (* egavga2exe *)
  1145.      :
  1146.    Incidentally, although this is a slightly different matter, you
  1147. can link any data material into your executable. See Stephen
  1148. O'Brien, (1988), Turbo Pascal, Advanced Programmer's Guide, pp. 31 -
  1149. 35 for more details.
  1150. --------------------------------------------------------------------
  1151.  
  1152. From ts@uwasa.fi Wed Aug 18 00:00:25 1993
  1153. Subject: Trapping runtime errors
  1154.  
  1155. 25. *****
  1156.  Q: How can I trap a runtime error?
  1157.  
  1158.  A: What you are probably asking for is a method writing a program
  1159. termination routine of your own. To do this, you have to replace
  1160. Turbo Pascal's ExitProc with your own customized exec procedure.
  1161. Several Turbo Pascal text books show ho to do this. See eg Tom Swan
  1162. (1989), Mastering Turbo Pascal 5.5, Third edition, Hayden Books, pp.
  1163. 440-454; Michael Yester (1989), Using Turbo Pascal, Que, pp.
  1164. 376-382; Stephen O'Brien (1988), Turbo Pascal, Advanced Programmer's
  1165. Guide, pp. 28-30; Tom Rugg & Phil Feldman (1989), Turbo Pascal
  1166. Programmer's Toolkit, Que, pp. 510-515. Here is an example
  1167.   var OldExitProcAddress : Pointer;
  1168.       x : real;
  1169.   {$F+} procedure MyExitProcedure; {$F-}
  1170.   begin
  1171.     if ErrorAddr <> nil then
  1172.       begin
  1173.         writeln ('Runtime error number ', ExitCode, ' has occurred');
  1174.         writeln ('The error address in decimal is ',
  1175.                   Seg(ErrorAddr^):5,':',Ofs(ErrorAddr^):5);
  1176.         writeln ('That''s all folks, bye bye');
  1177.         ErrorAddr := nil;
  1178.         ExitCode  := 0;
  1179.       end;
  1180.     {... Restore the pointer to the original exit procedure ...}
  1181.     ExitProc := OldExitProcAddress;
  1182.   end;  (* MyExitProcedure *)
  1183.   (* Main *)
  1184.   begin
  1185.     OldExitProcAddress := ExitProc;
  1186.     ExitProc := @MyExitProcedure;
  1187.     x := 7.0; writeln (1.0/x);
  1188.     x := 0.0; writeln (1.0/x);   {The trap}
  1189.     x := 7.0; writeln (4.0/x);   {We won't get this far}
  1190.   end.
  1191. :
  1192. Actually, I utilize this idea in my /pc/ts/tspa33??.zip Turbo Pascal
  1193. units collection, which includes a TSERR.TPU. If you put TSERR in
  1194. your program's uses statement, all the run time errors will be given
  1195. verbally besides the usual, cryptic error number. That's all there
  1196. is to it. That is, the inclusion to the uses statment to your main
  1197. program (if you have the program in several units) is all you have
  1198. to do to enable this handy feature.
  1199. --------------------------------------------------------------------
  1200.  
  1201. From ts@uwasa.fi Wed Aug 18 00:00:26 1993
  1202. Subject: Using ansi codes in a TP program
  1203.  
  1204. 26. *****
  1205.  Q: How to get ansi control codes working in Turbo Pascal writes?
  1206.  
  1207.  A: It is very simple, but one has to be aware of the pitfalls.
  1208. Let's start from the assumption that ansi.sys or a corresponding
  1209. driver has been loaded, and that you know ansi codes. If you don't,
  1210. you'll find that information in the standard MsDos manual. To apply
  1211. ansi codes you just include the ansi codes in your write statements.
  1212. For example the following first clears the screen and then puts the
  1213. text at location 10,10:
  1214.    write (#27, '[2J');         (* the ascii code for ESC is 27 *)
  1215.    write (#27, '[10;10HUsing ansi codes can be fun');
  1216. If you want to test (as you should) whether ansi.sys or some some
  1217. replacement driver has been loaded, you can use the ISANSIFN
  1218. function from my garbo.uwasa.fi:/pc/ts/tspa33??.zip.
  1219. Now the catches. If you have a
  1220.    uses Crt;
  1221. statement in your program, direct screen writes will be used, and
  1222. the ansi codes won't work. You have either to leave out the Crt
  1223. unit, or include
  1224.    assign (output, '');
  1225.    rewrite (output);
  1226.    :
  1227.    close (output);
  1228. Occasionally I have seen it suggested that one should just set
  1229.    DirectVideo := false;
  1230. This is a popular misconception. It won't produce the desired
  1231. result. I'm not claiming to know the reason for this quirk of Turbo
  1232. Pascal. Rather it is an observation I've made.
  1233.  
  1234. -From: Bengt Oehman (d92bo@efd.lth.se)
  1235. The `DirectVideo:=False' statement only tells the Crt unit to use
  1236. BIOS calls instead of using direct video-memory writes. A demo
  1237. program to illustrate the screen writing modes follows:
  1238.  
  1239. Program ScreenWriteDemo;
  1240. USES Crt;
  1241. BEGIN
  1242.   Writeln('This is written directly to the video memory');
  1243.   DirectVideo:=False;
  1244.   Writeln('This is written via BIOS interrupt calls (int 10h)');
  1245.   Assign(Output,'');
  1246.   Append(Output);
  1247.   Writeln('This is written via DOS calls (int 21h)');
  1248. END.
  1249. --------------------------------------------------------------------
  1250.  
  1251. From ts@uwasa.fi Wed Aug 18 00:00:27 1993
  1252. Subject: Writing an expression parser
  1253.  
  1254. 27. *****
  1255.  Q: How to evaluate a function given as a string to the program?
  1256.  
  1257.  A: To do this you have to have a routine for parsing and evaluating
  1258. your expression. This is a complicated task requiring a clever use
  1259. of recursion. You can find such code in Stephen O'Brien (1988),
  1260. Turbo Pascal, The Complete Reference. Borland-Osborne/McGraw-Hill,
  1261. Chapter 10. Another, simpler piece of code can be found in Michael
  1262. Yester (1989), Using Turbo Pascal, Que, Chapter 5.
  1263.    I've also written such a function evaluation program myself, and
  1264. much of it is based on the ideas in O'Brien with my own corrections
  1265. and enhancements. The resulting program is available as fn.exe
  1266. function evaluator in the /pc/ts/tsfunc13.zip package (or whatever
  1267. version number is the latest). Note however, that the source code is
  1268. not included, nor available.
  1269.    Tips from Justin Lee (ossm1jl@rex.uokhsc.edu):
  1270. 9158 Apr 25 1992 garbo.uwasa.fi:/pc/turbopas/parse11.zip
  1271. parse11.zip Recursive expression Turbo Pascal parser from Ron Loewy
  1272. An excellent parser is included with all the Turbo Pascal versions
  1273. since TP4.0 as part of the MCALC or TCALC spreadsheet example
  1274. program. See mcparse.pas or tcparse.pas.
  1275. --------------------------------------------------------------------
  1276.  
  1277. From ts@uwasa.fi Wed Aug 18 00:00:28 1993
  1278. Subject: Detecting redirection
  1279.  
  1280. 28. *****
  1281.  Q: How does one detect whether input (or output) is redirected?
  1282.  
  1283.  A: As we know input to a program can come from a file, from the
  1284. console, or from a pipe or redirection. Examples of the latter are
  1285.      type text.dat | program
  1286.      program < text.dat
  1287. A Turbo Pascal program can be made to detect the redirections using
  1288. Interrupt 21Hex, function 44Hex, subfunction 00Hex. See PC Magazine
  1289. April 16, 1991, p. 374 for the code, and Duncan (1988), Advanced
  1290. MS-DOS Programming, pp. 412-413 for more information. Alternatively,
  1291. you can utilize the preprogrammed routines
  1292.   PIPEDIFN Is the standard input from redirection
  1293.   PIPEDNFN Is the standard output redirected to nul
  1294.   PIPEDOFN Is the standard output redirected
  1295. from my garbo.uwasa.fi:/pc/ts/ tspa33??.zip units.
  1296. --------------------------------------------------------------------
  1297.  
  1298. From ts@uwasa.fi Wed Aug 18 00:00:29 1993
  1299. Subject: Setting the 43/50 line text mode
  1300.  
  1301. 29. *****
  1302.  Q: How does one set the 43/50 line text mode?
  1303.  
  1304.  A: Quite simple. Just apply TextMode (C80 + font8x8).  Requires a
  1305. "uses Crt;". First, however, you should test that you have a at
  1306. least an EGA video adapter. (See DetectGraph in your TP manual).
  1307. Also see TSUTLE.NWS in garbo.uwasa.fi:/pc/ts/tsutle22.zip (or
  1308. whichever version number is the current) for the non-standard wide
  1309. text modes like 132x43.
  1310. --------------------------------------------------------------------
  1311.  
  1312. From ts@uwasa.fi Wed Aug 18 00:00:30 1993
  1313. Subject: Assigning environment variable values
  1314.  
  1315. 30. *****
  1316.  Q: How can I assign a value to an environment variable in TP?
  1317.  
  1318.  A: For assigning a value to (a parent process's) environment value
  1319. you have to access and manipulate the Program Segment Prefix and
  1320. Memory Control Blocks. This is a rather complicated undertaking. A
  1321. source code with an accompanying article by Trudy Neuhaus can be
  1322. found in PC Magazine Volume 11 Number 1 pages 425-427.
  1323.    The budding TP programmers should note that the elementary trick
  1324. of Exec (GetEnv('comspec'), '/c set key=whatever') will achieve only
  1325. a transient result for the duration of the exec shell. When you exit
  1326. the shell after this endeavor, the environment will be as it was.
  1327.    Here is about the why. When the above command is executed, MsDos
  1328. makes a copy of the environment, and uses the copy. When the above
  1329. shelling terminates, the copy of the environment is deleted, and the
  1330. original is restored. Hence the above trick cannot be used to change
  1331. the parent environment.
  1332.    If you don't want to try to go through this rather complicated
  1333. task yourself, the routines
  1334.  "SETENV   Set a parent environment variable (variable=value)"
  1335.  "SETENVSH Set an environment variable for the duration of shelling"
  1336. can be found in my TP TPU collection garbo.uwasa.fi:/pc/ts/
  1337. tspa33*.zip (* = 40,50,55,60,70). No source code is included, nor
  1338. available, though.
  1339. --------------------------------------------------------------------
  1340.